<!DOCTYPE html>
<!--
@license
Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<html>
<head>
  <meta charset="UTF-8">
  <script src="../../node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js"></script>
  <script src="wct-browser-config.js"></script>
  <script src="../../node_modules/wct-browser-legacy/browser.js"></script>
  <script type="module">
    import { setRootPath } from '../../lib/utils/settings.js';
    setRootPath('earlyRootPath/');
  </script>
  <script type="module" src="../../polymer-legacy.js"></script>
  <script type="module" src="./sub/resolveurl-elements.js"></script>
</head>
<body>
  <x-resolve></x-resolve>

  <dom-module id="x-late">
    <template>
      <style>
        :host {
          background: url('foo.png');
        }
      </style>
      <img id="root" src$="[[rootPath]]foo.png">
      <img id="import" src$="[[importPath]]foo.png">
    </template>
  </dom-module>

  <dom-module id="x-resolve">
  </dom-module>

  <script type="module">
import './sub/resolveurl-elements.js';
import { PolymerElement } from '../../polymer-element.js';
class XResolve extends PolymerElement {
  static get is() { return 'x-resolve'; }
}
customElements.define(XResolve.is, XResolve);
</script>


  <script type="module">
import './sub/resolveurl-elements.js';
import { PolymerElement } from '../../polymer-element.js';
import { setRootPath } from '../../lib/utils/settings.js';
suite('ResolveUrl', function() {

  const testStylesAndAttributes = (elementName) => () => {
    var el = document.createElement(elementName);
    document.body.appendChild(el);
    var resolvedUrl = /sub\/foo\.z/;
    var styleHashUrl = /url\('#bar'\)/;
    var styleAbsUrl = /url\('\/zot'\)/;
    var style = el.shadowRoot.querySelector('style') || document.querySelector(`style[scope=${elementName}]`);
    assert.match(style.textContent, resolvedUrl, 'url not relative to main document');
    assert.match(style.textContent, styleHashUrl, 'hash url incorrectly resolved');
    assert.match(style.textContent, styleAbsUrl, 'absolute url incorrectly resolved');
    assert.match(el.$.div.getAttribute('style'), resolvedUrl, 'style url not relative to main document');
    assert.match(el.$.img.src, resolvedUrl, 'src url not relative to main document');
    assert.match(el.$.a.href, resolvedUrl, 'href url not relative to main document');
    assert.match(el.$.import.getAttribute('url'), resolvedUrl, 'url url not relative to main document');
    assert.match(el.$.resolveUrl.getAttribute('url'), resolvedUrl, 'url url not relative to main document');
    assert.equal(el.$.resolveUrlHash.getAttribute('url'), '#foo', 'url url not relative to main document');
    assert.equal(el.$.resolveUrlAbs.getAttribute('url'), '/foo', 'url url not relative to main document');
    assert.notMatch(el.$.root.getAttribute('url'), resolvedUrl, 'url url not relative to main document');
    assert.notMatch(el.$.rel.href, resolvedUrl, 'relative href url not relative to main document');
    assert.match(el.$.rel.href, /\?123$/, 'relative href does not preserve query string');
    assert.equal(el.$.action.getAttribute('action'), 'foo.z', 'action attribute relativized for incorrect element type');
    assert.match(el.$.formAction.action, resolvedUrl, 'action attribute relativized for incorrect element type');
    assert.equal(el.$.hash.getAttribute('href'), '#foo.z', 'hash-only url should not be resolved');
    assert.equal(el.$.absolute.getAttribute('href'), '/foo.z', 'absolute urls should not be resolved');
    assert.equal(el.$.protocol.getAttribute('href'), 'data:foo.z', 'urls with other protocols should not be resolved');
    document.body.removeChild(el);
  };

  test('Urls in styles and attributes', testStylesAndAttributes('p-r'));

  test('Urls in styles and attributes (hybrid)', testStylesAndAttributes('p-r-hybrid'));

  test('url changes via setting importPath/rootPath on element instance', function() {
    var el = document.createElement('p-r');
    document.body.appendChild(el);
    el.rootPath = 'instanceRoot/';
    el.importPath = 'instanceImport/';
    var matchRoot = /instanceRoot\//;
    var matchImport = /instanceImport\//;
    assert.match(el.$.div.getAttribute('style'), matchImport);
    assert.match(el.$.import.getAttribute('url'), matchImport);
    assert.match(el.$.root.getAttribute('url'), matchRoot);
    document.body.removeChild(el);
  });

  test('rootPath set early', function() {
    class XEarly extends PolymerElement {
      static get is() { return 'x-late';}
    }
    customElements.define('x-early', XEarly);
    var el = document.createElement('x-early');
    document.body.appendChild(el);
    var matchRoot = /earlyRootPath\//i;
    assert.match(el.$.root.getAttribute('src'), matchRoot);
    document.body.removeChild(el);
  });

  test('url changes via setting importPath/rootPath when defining element', function() {
    setRootPath('defineRoot/');
    class XLate extends PolymerElement {
      static get is() { return 'x-late';}
      static get importPath() { return 'defineImport/';}
    }
    customElements.define(XLate.is, XLate);
    var el = document.createElement('x-late');
    document.body.appendChild(el);
    var matchRoot = /defineRoot\//i;
    var matchImport = /defineImport\//i;
    var style = el.shadowRoot.querySelector('style') || document.querySelector('style[scope=x-late]');
    assert.match(style.textContent, matchImport);
    assert.match(el.$.import.getAttribute('src'), matchImport);
    assert.match(el.$.root.getAttribute('src'), matchRoot);
    document.body.removeChild(el);
  });

  test('resolveUrl api', function() {
    var el = document.createElement('p-r');
    var expected = document.location.href.replace(/[?#].*$/, '');
    var actual = el.resolveUrl('../resolveurl.html');
    assert.equal(actual, expected);
  });

  test('resolveUrl api with base', function() {
    var el = document.createElement('p-r');
    var expected = 'http://example.com/resolveurl.html';
    var actual = el.resolveUrl('resolveurl.html', 'http://example.com/');
    assert.equal(actual, expected);
  });

  test('resolveUrl api, when defined in main doc', function() {
    var el = document.querySelector('x-resolve');
    var expected = document.location.href.replace(/[?#].*$/, '');
    expected = expected.split('/');
    expected.pop();
    expected = expected.join('/') + '/foo/bar.png';
    var actual = el.resolveUrl('foo/../foo/bar.png');
    assert.equal(actual, expected);
  });

  test('resolveUrl when called with a protocol-relative url', function () {
    const el = document.querySelector('x-resolve');
    const expected = `https://example.com/foo`;
    const actual =
        el.resolveUrl('//example.com/foo', 'https://example.org/bar');
    assert.equal(actual, expected);
  });

  test('resolveUrl when called with //', function () {
    const el = document.querySelector('x-resolve');
    const expected = '//';
    const actual =
        el.resolveUrl('//', 'https://example.org/bar');
    assert.equal(actual, expected);
  });

  test('resolveUrl when called with relative url and a bad baseURI', function () {
    const el = document.querySelector('x-resolve');
    const expected = 'relative/path.png';
    const actual =
        el.resolveUrl('relative/path.png', '/not/a/full/uri');
    assert.equal(actual, expected);
  });

  test('resolveUrl when called with a full url and a bad baseURI', function () {
    const el = document.querySelector('x-resolve');
    const expected = 'https://example.com/foo.png';
    const actual =
        el.resolveUrl('https://example.com/foo.png', '/not/a/full/uri');
    assert.equal(actual, expected);
  });

  test('resolveUrl when called with a protocol-relative url and a bad baseURI', function () {
    const el = document.querySelector('x-resolve');
    const expected = '//example.com/foo.png';
    const actual =
        el.resolveUrl('//example.com/foo.png', '/not/a/full/uri');
    assert.equal(actual, expected);
  });

  test('resolveUrl api with assetpath', function() {
    var el = document.createElement('p-r-ap');
    // Manually calculate expected URL, to avoid dependence on
    // URL object for this test for IE! Otherwise, would do this:
    // var importPath = document.querySelector('#elements').href;
    // var expected = new URL('../../assets/Beaker2.jpg', importPath);
    var expected = document.location.href.replace(/[?#].*$/, '');
    expected = expected.split('/');
    expected.pop();
    expected.pop();
    expected = expected.join('/');
    expected = expected + '/assets/Beaker2.jpg';
    var actual = el.resolveUrl('Beaker2.jpg');
    assert.equal(actual, expected);
  });
});
</script>
</body>
</html>
